﻿
using CSharpLibs.Annotations;
using System.Collections;
using System.Collections.Generic;

namespace System
{
	[Builtin]
	public abstract class Array : Object
	{
		internal Array()
		{
		}

		public int Length 
		{
			[BuiltinMethod, BuiltinSemantics("array_length")]
			get { return -1; } 
		}

		public static int BinarySearch<T0>(T0[] array, T0 value)
		{
			int low = 0;
			int hi = array.Length;

			while(low <= hi)
			{
				int num6;
				int num5 = GetMedian(low, hi);

				num6 = Comparer<T0>.DefaultCompare(array[num5], value);

				if(num6 == 0)
					return num5;
				
				if(num6 < 0)
					low = num5 + 1;
				else
					hi = num5 - 1;
			}

			return ~low;
		}

		public static int BinarySearch<T0>(T0[] array, T0 value, Comparer<T0> comparer)
		{
			int low = 0;
			int hi = array.Length;

			while(low <= hi)
			{
				int num6;
				int num5 = GetMedian(low, hi);

				num6 = comparer.Compare(array[num5], value);

				if(num6 == 0)
					return num5;
				if(num6 < 0)
					low = num5 + 1;
				else
					hi = num5 - 1;
			}

			return ~low;
		}

		private static int GetMedian(int low, int hi)
		{ return (low + ((hi - low) >> 1)); }

		public static void Clear<T0>(T0[] array, int index, int length)
		{
            for (int i = 0; i < length; ++i)
                array[i + index] = default(T0);
        }

        [BuiltinMethod, BuiltinSemantics("array_clone")]
		public object Clone()
		{ return null; }

		public static void Copy<T0>(T0[] sourceArray, T0[] destinationArray, int length)
		{
			if(sourceArray == destinationArray)
				sourceArray = (T0[])sourceArray.Clone();

			for(int i = 0; i < length; ++i)
				destinationArray[i] = sourceArray[i];
		}

		public static void Copy<T0>(T0[] sourceArray, int sourceIndex, T0[] destinationArray, int destinationIndex, int length)
		{
			if(sourceArray == destinationArray)
				sourceArray = (T0[])sourceArray.Clone();

			for(int i = 0; i < length; ++i)
				destinationArray[i + destinationIndex] = sourceArray[i + sourceIndex];
		}

		public static bool Contains<T0>(T0 value, T0[] array, int start, int count)
		{
			int num = start + count;
			for(int i = start; i < num; i++)
			{
				if(EqualityComparer<T0>.DefaultEquals(value, array[i]))
					return true;
			}

			return false;
		}

		public static bool Exists<T0>(T0[] array, Predicate<T0> match)
		{
			for(int i = 0; i < array.Length; i++)
			{
				if(match(array[i]))
					return true;
			}

			return false;
		}

		public static bool Exists<T0>(T0[] array, int start, int count, Predicate<T0> match)
		{
			int num = start + count;
			for(int i = start; i < num; i++)
			{
				if(match(array[i]))
					return true;
			}

			return false;
		}

		public static T0 Find<T0>(T0[] array, Predicate<T0> match)
		{
			for(int i = 0; i < array.Length; i++)
			{
				if(match(array[i]))
					return array[i];
			}

			return default(T0);
		}

		public static T0 Find<T0>(T0[] array, int start, int count, Predicate<T0> match)
		{
			int num = start + count;
			for(int i = start; i < num; i++)
			{
				if(match(array[i]))
					return array[i];
			}

			return default(T0);
		}

		public static int FindIndex<T0>(T0[] array, Predicate<T0> match)
		{
			for(int i = 0; i < array.Length; i++)
			{
				if(match(array[i]))
					return i;
			}

			return -1;
		}

		public static int FindIndex<T0>(T0[] array, int startIndex, int count, Predicate<T0> match)
		{
			int num = startIndex + count;
			for(int i = startIndex; i < num; i++)
			{
				if(match(array[i]))
					return i;
			}

			return -1;
		}

		public static T0 FindLast<T0>(T0[] array, Predicate<T0> match)
		{
			for(int i = array.Length - 1; i > 0; i--)
			{
				if(match(array[i]))
					return array[i];
			}

			return default(T0);
		}

		public static T0 FindLast<T0>(T0[] array, int startIndex, int count, Predicate<T0> match)
		{
			int num = startIndex - count;
			for(int i = startIndex; i > num; i--)
			{
				if(match(array[i]))
					return array[i];
			}

			return default(T0);
		}

		public static int FindLastIndex<T0>(T0[] array, Predicate<T0> match)
		{
			for(int i = array.Length - 1; i > 0; i--)
			{
				if(match(array[i]))
					return i;
			}

			return -1;
		}

		public static int FindLastIndex<T0>(T0[] array, int startIndex, int count, Predicate<T0> match)
		{
			int num = startIndex - count;
			for(int i = startIndex; i > num; i--)
			{
				if(match(array[i]))
					return i;
			}

			return -1;
		}

		public static void ForEach<T0>(T0[] array, Action<T0> action)
		{
			for(int i = 0; i < array.Length; i++)
				action(array[i]);
		}

		public static void ForEach<T0>(T0[] array, int start, int count, Action<T0> action)
		{
			int end = start + count;
			for(int i = start; i < end; i++)
				action(array[i]);
		}

		public static int IndexOf<T0>(T0[] array, T0 value)
		{
			for(int i = 0; i < array.Length; ++i)
			{
				if(EqualityComparer<T0>.DefaultEquals(value, array[i]))
					return i;
			}

			return -1;
		}

		public static int IndexOf<T0>(T0[] array, T0 value, int startIndex, int count)
		{
			int end = startIndex + count;
			for(int i = startIndex; i < end; ++i)
			{
				if(EqualityComparer<T0>.DefaultEquals(value, array[i]))
					return i;
			}

			return -1;
		}

		public static int LastIndexOf<T0>(T0[] array, T0 value)
		{
			for(int i = array.Length - 1; i >= 0; i--)
			{
				if(EqualityComparer<T0>.DefaultEquals(array[i], value))
					return i;
			}

			return -1;
		}

		public static int LastIndexOf<T0>(T0[] array, T0 value, int startIndex, int count)
		{
			int num = (startIndex - count) + 1;
			for(int i = startIndex; i >= num; i--)
			{
				if(EqualityComparer<T0>.DefaultEquals(array[i], value))
					return i;
			}

			return -1;
		}

		[BuiltinMethod, BuiltinSemantics("array_resize")]
		public static void Resize<T0>(ref T0[] array, int newSize)
		{ ;}

		public static void Reverse<T0>(T0[] array)
		{
			int num = 0;
			int num2 = array.Length;

			while(num < num2)
			{
				T0 obj2 = array[num];
				array[num] = array[num2];
				array[num2] = obj2;

				num++;
				num2--;
			}
		}

		public static void Reverse<T0>(T0[] array, int index, int length)
		{
			int num = index;
			int num2 = (index + length) - 1;
			while(num < num2)
			{
				T0 obj2 = array[num];
				array[num] = array[num2];
				array[num2] = obj2;

				num++;
				num2--;
			}
		}

		public static void Sort<T0>(T0[] array)
		{
			for(int k = 0; k < gaps.Length; ++k)
			{
				int gap = gaps[k];
				for(int i = gap; i < array.Length; i++)
				{
					T0 vtoins = array[i];
					int cpos = i;
					while(cpos > 0 && Comparer<T0>.DefaultCompare(vtoins, array[cpos - 1]) < 0)
					{
						array[cpos] = array[cpos - 1];
						cpos = cpos - 1;
					}
					array[cpos] = vtoins;
				}
			}
		}

		public static void Sort<T0>(T0[] array, Comparer<T0> comparer)
		{
			for(int k = 0; k < gaps.Length; ++k)
			{
				int gap = gaps[k];
				for(int i = gap; i < array.Length; i++)
				{
					T0 vtoins = array[i];
					int cpos = i;
					while(cpos > 0 && comparer.Compare(vtoins, array[cpos - 1]) < 0)
					{
						array[cpos] = array[cpos - 1];
						cpos = cpos - 1;
					}
					array[cpos] = vtoins;
				}
			}
		}

		public static bool TrueForAll<T0>(T0[] array, Predicate<T0> match)
		{
			for(int i = 0; i < array.Length; i++)
			{
				if(!match(array[i]))
					return false;
			}

			return true;
		}

		public static bool TrueForAll<T0>(T0[] array, int start, int count, Predicate<T0> match)
		{
			int end = start + count;
			for(int i = start; i < end; i++)
			{
				if(!match(array[i]))
					return false;
			}

			return true;
		}

		//////////////////////////////
		//Sort herlpers

		private static int[] gaps;

		static Array()
		{
			gaps = new int[8];
			gaps[0] = 701;
			gaps[1] = 301;
			gaps[2] = 132;
			gaps[3] = 57;
			gaps[4] = 23;
			gaps[5] = 10;
			gaps[6] = 4;
			gaps[7] = 1;
		}
	}
}
